package com.lijiajia.cloud.authserver.configuration.security.authserver;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.security.oauth2.authserver.AuthorizationServerProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.token.AccessTokenConverter;
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
import org.springframework.security.oauth2.provider.token.TokenStore;

/**
 * com.lijiajia.cloud.auth.server.config.security.authserver description
 *
 * @author lijiajia
 * @since 2019-05-28
 */
@Slf4j
@Configuration
public class AuthorizationServerConfigurer implements org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurer {
    private final AuthorizationServerProperties authServerProperties;
    private final PasswordEncoder clientPasswordEncoder;
    private final ClientDetailsService clientDetailsService;
    private final AuthenticationManager authenticationManager;
    private final UserDetailsService usernameUserService;
    private final TokenStore tokenStore;
    private final AccessTokenConverter accessTokenConverter;
    private final TokenEnhancer tokenEnhancer;


    public AuthorizationServerConfigurer(AuthorizationServerProperties authServerProperties,
                                         @Qualifier("clientPasswordEncoder") PasswordEncoder clientPasswordEncoder,
                                         @Qualifier("authServerClientDetailsService") ClientDetailsService clientDetailsService,
                                         AuthenticationManager authenticationManager,
                                         @Qualifier("usernameUserService") UserDetailsService usernameUserService,
                                         @Qualifier("authServerTokenEnhancer") TokenEnhancer tokenEnhancer,
                                         @Qualifier("authServerAccessTokenConverter") AccessTokenConverter accessTokenConverter,
                                         @Qualifier("authServerTokenStore") TokenStore tokenStore) {
        this.authServerProperties = authServerProperties;
        this.clientPasswordEncoder = clientPasswordEncoder;
        this.clientDetailsService = clientDetailsService;
        this.authenticationManager = authenticationManager;
        this.usernameUserService = usernameUserService;
        this.tokenEnhancer = tokenEnhancer;
        this.accessTokenConverter = accessTokenConverter;
        this.tokenStore = tokenStore;
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        log.debug("configure oauth server security");
        security.realm(authServerProperties.getRealm())
                .checkTokenAccess(authServerProperties.getCheckTokenAccess())
                .tokenKeyAccess(authServerProperties.getTokenKeyAccess())
                .allowFormAuthenticationForClients()
                .passwordEncoder(clientPasswordEncoder);
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        log.debug("configure oauth server clients");
        clients.withClientDetails(clientDetailsService);
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints
                .tokenStore(tokenStore)
                .tokenEnhancer(tokenEnhancer)
                .accessTokenConverter(accessTokenConverter)
                .authenticationManager(authenticationManager)
                .userDetailsService(usernameUserService);
    }
}
